package com.example.productserver.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.productserver.entity.Product;
import com.example.productserver.mapper.ProductMapper;
import com.example.productserver.service.IProductTccService;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author whx
 * @date 2022/4/30
 */
@Slf4j
@Service
public class IProductTccServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductTccService {

    /**
     * Transactional 添加行锁，防止多线程下更新库存时被其他线程读取到脏数据，这样能保证第一次获取时FrozenInventory为0
     * @param productId
     * @param number
     * @return
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public String reduceInventory(Long productId,Integer number) {
        Product product = this.getOne(Wrappers.<Product>lambdaQuery()
                .select(Product::getId,Product::getInventory,Product::getFrozenInventory)
                .eq(Product::getId,productId));
        // 当前可用库存需要排除历史冻结库存
        if(product.getInventory() >= number){
            // 更新冻结库存
            product.setFrozenInventory(number);
            this.updateById(product);
            return "库存更新成功";
        }
        return "商品库存不足";

    }

    @Override
    public boolean reduceCommit(BusinessActionContext context) {
        Product product = this.getOne(Wrappers.<Product>lambdaQuery()
                .select(Product::getId,Product::getInventory,Product::getFrozenInventory)
                .eq(Product::getId,context.getActionContext("goodsId")));
        Integer number = Integer.parseInt(context.getActionContext("number").toString());
        if (product != null) {
            //扣减库存
            product.setInventory(product.getInventory() - number);
            product.setFrozenInventory(0);
            this.saveOrUpdate(product);
        }
        log.info("事务 xid="+context.getXid()+" 提交成功");
        return true;
    }

    @Override
    public boolean reduceRollBack(BusinessActionContext context) {
        Product product = this.getOne(Wrappers.<Product>lambdaQuery()
                .select(Product::getId,Product::getFrozenInventory)
                .eq(Product::getId,context.getActionContext("goodsId")));
        Integer number = Integer.parseInt(context.getActionContext("number").toString());
        if (product != null) {
            // 恢复冻结库存
            product.setFrozenInventory(0);
            this.saveOrUpdate(product);
        }
        log.info("事务 xid="+context.getXid()+" 回滚成功");
        return true;
    }
}
